import { summary } from './functions/summary.js';
import { getRate, getGrade } from './functions/addition.js';
import Life from './life.js';
import specialthanks from '../data/specialthanks.json';
import {LR_STATGE,DEFAULT_TALENT_RANDOM_SIZE,DEFAULT_PROPERTY_TOTAL_BASE, stageHelper} from '../constants/lr_constants.js';
import LifeRestartStage from './lifeRestartStage.js'
import {$$on,$$event} from './lifeRestartEventBus.js'
import storage from "./functions/storage.js"

class App{
    constructor(){
        this.#life = new Life();
    }

    #life;
    #pages;
    #currentPage;
	#currentPageEntity;
    #talentSelected = new Set();
	#randomTalentList = [];
    #totalMax=DEFAULT_PROPERTY_TOTAL_BASE;
    #isEnd = false;
    #selectedExtendTalent = null;
    #hintTimeout;
    #specialthanks;
    #autoTrajectory;
	#stageChangeFunc;
	#trajectoryList = [];
	#selectTalentChangeFunc;
	#lifePropertyChangeFunc;
	#trajectoryFunc ={
		lifePropertyChange:null,
		contentChange:null
	};
	
	#talentSelectMax  = 3;
	#restartStage = LR_STATGE.loading.code;

    initial(stageChangeFunc) {
        this.initPages();
		this.#life.initial();
		this.#specialthanks = specialthanks;
		this.#stageChangeFunc = stageChangeFunc;
        
        
    };
	doTrigger = (fname)=>{
		if("trajectory.lifePropertyChange" == fname){
			if(this.#trajectoryFunc.lifePropertyChange){
				this.#trajectoryFunc.lifePropertyChange(this.#life.getLastRecord());
			}
		}
		if("trajectory.contentChange" == fname){
			if((!this.#isEnd) && this.#trajectoryList.length > 0){
				this.#isEnd = this.#trajectoryList[this.#trajectoryList.length-1].isEnd;
			}
			if(this.#trajectoryFunc.contentChange){
				this.#trajectoryFunc.contentChange(this.#trajectoryList);
			}
		}
	};
    initPages() {

        // Loading
        const loadingPage = new LifeRestartStage(LR_STATGE.loading.code);

        // Index
        const indexPage = new LifeRestartStage(LR_STATGE.index.code);
		
		console.log("storage",storage);
        // Init theme
        this.setTheme(storage.getItem('theme'))



        const specialThanksPage = new LifeRestartStage(LR_STATGE.specialThanks.code);

        
        const achievementPage = new LifeRestartStage(null);

       
        // Talent
        const talentPage = new LifeRestartStage(LR_STATGE.talent.code);

        const createTalent = ({ grade, name, description }) => {
            return { grade, name, description };
        };
		talentPage.preNextStage = ()=>{
			
		}
        
        // Property
        // hint of extension tobermory.es6-string-html
        const propertyPage = new LifeRestartStage(LR_STATGE["property"].code);
        propertyPage.mounted = ()=>{
            this.#totalMax = DEFAULT_PROPERTY_TOTAL_BASE + this.#life.getTalentAllocationAddition(Array.from(this.#talentSelected).map(({id})=>id));
            freshTotal();
        }
        const groups = {};
        const total = ()=>{
            let t = 0;
            for(const type in groups)
                t += groups[type].get();
            return t;
        }
		
        const freshTotal = ()=>{
            if(this.#lifePropertyChangeFunc){
				let propertyGroups = groups;
				let propertyGroupsList = [];
				for(let key in propertyGroups){
					propertyGroupsList.push({
						type: key,
						value: propertyGroups[key],
						name: propertyGroups[key].group.name
					})
				}
				let setedTotal = total();
				let remainTotal = this.#totalMax - setedTotal;
				let lifePropData ={
					"totalMax":this.#totalMax,
					"setedTotal":setedTotal,
					"remainTotal":remainTotal,
					"propertyGroups":propertyGroups,
					"propertyGroupsList":propertyGroupsList
				};
				this.#lifePropertyChangeFunc(lifePropData);
			}
        }
		
        const getBtnGroups = (name, min, max)=>{
            const group = {
				"name":name
			};
            const btnSub = {};
            const inputBox = (function(){ 
				let aval = 0;
				let obj = {
					val(v){
						if(v || v===0){
							aval = v;
						}
						return aval;
					}
				}
				return obj;
			})();
            

            const limit = v=>{
                v = Number(v)||0;
                v = Math.round(v);
                return v < min ? min : (
                    v > max ? max : v
                )
            }
            const get = ()=>Number(inputBox.val());
            const set = v=>{
                inputBox.val(limit(v));
                freshTotal();
            }
            const add = ()=>{
                if(total() >= this.#totalMax) {
                    this.hint('没有可分配的点数了');
                    return;
                }
                set(get()+1);
            };
            const sub = ()=>set(get()-1);
            const input = ()=>{
                const t = total();
                let val = get();
                if(t > this.#totalMax) {
                    val -= t - this.#totalMax;
                }
                val = limit(val);
                if(val != inputBox.val()) {
                    set(val);
                }
                freshTotal();
            };
			
            return {group, get, set, add,sub, input};
        }

        groups.CHR = getBtnGroups("颜值", 0, 10); // 颜值 charm CHR
        groups.INT = getBtnGroups("智力", 0, 10); // 智力 intelligence INT
        groups.STR = getBtnGroups("体质", 0, 10); // 体质 strength STR
        groups.MNY = getBtnGroups("家境", 0, 10); // 家境 money MNY

        

        propertyPage.random = ()=>{
                let t = this.#totalMax;
                const arr = [10, 10, 10, 10];
                while(t>0) {
                    const sub = Math.round(Math.random() * (Math.min(t, 10) - 1)) + 1;
                    while(true) {
                        const select = Math.floor(Math.random() * 4) % 4;
                        if(arr[select] - sub <0) continue;
                        arr[select] -= sub;
                        t -= sub;
                        break;
                    }
                }
                groups.CHR.set(10 - arr[0]);
                groups.INT.set(10 - arr[1]);
                groups.STR.set(10 - arr[2]);
                groups.MNY.set(10 - arr[3]);
            };

        propertyPage.clickStart = ()=>{
                if(total() < this.#totalMax) {
                    this.hint(`你还有${this.#totalMax-total()}属性点没有分配完`);
                    return false;
                } else if (total() > this.#totalMax) {
                    this.hint(`你多使用了${total() - this.#totalMax}属性点`);
                    return false;
                }
                const contents = this.#life.restart({
                    CHR: groups.CHR.get(),
                    INT: groups.INT.get(),
                    STR: groups.STR.get(),
                    MNY: groups.MNY.get(),
                    SPR: 5,
                    TLT: Array.from(this.#talentSelected).map(({id})=>id),
                });
                this.switch('trajectory');
                this.#pages.trajectory.born(contents);
                // $(document).keydown(function(event){
                //     if(event.which == 32 || event.which == 13){
                //         $('#lifeTrajectory').click();
                //     }
                // })
				return true;
            };

        // Trajectory
        const trajectoryPage = new LifeRestartStage(LR_STATGE.trajectory.code);
		
        trajectoryPage.mounted = ()=>{
			this.#trajectoryList = [];
			this.doTrigger("trajectory.lifePropertyChange");
			this.doTrigger("trajectory.contentChange");
		};

        

        

        // Summary
        const summaryPage = new LifeRestartStage(LR_STATGE.summary.code);;

        

        this.#pages = {
            [LR_STATGE.loading.pageCode]: {
                page: loadingPage,
                clear: ()=>{
                    this.#currentPage = 'loading';
                },
				
            },
            [LR_STATGE.index.pageCode]: {
                page: indexPage,
				
                
                pressEnter: ()=>{
                    this.#pages.index.btnRestart.click();
                },
                clear: ()=>{
                    this.#currentPage = 'index';
                    

                    
                },
            },
            [LR_STATGE.specialThanks.pageCode]: {
                page: specialThanksPage,
				
                clear: () => {
                    
                    
                }
            },
            [LR_STATGE.achievement.pageCode]: {
                page: achievementPage,
                clear: () => {
                    

                    const formatRate = (type, value) => {
                        const rate = getRate(type, value);
                        let color = Object.keys(rate)[0];
                        switch(parseInt(color)) {
                            case 0: color = '白色'; break;
                            case 1: color = '蓝色'; break;
                            case 2: color = '紫色'; break;
                            case 3: color = '橙色'; break;
                            default: break;
                        }
                        let r = Object.values(rate)[0];
                        switch(parseInt(r)) {
                            case 1: r = '不变'; break;
                            case 2: r = '翻倍'; break;
                            case 3: r = '三倍'; break;
                            case 4: r = '四倍'; break;
                            case 5: r = '五倍'; break;
                            case 6: r = '六倍'; break;
                            default: break;
                        }
                        return `抽到${color}概率${r}`;
                    }

                    const { times, achievement, talentRate, eventRate } = this.#life.getTotal();
                    
                    const achievementsData = this.#life.getAchievements();
                    achievementsData.forEach(({
                        name, description, hide,
                        grade, isAchieved
                    })=>{
                        if(hide && !isAchieved) name = description = '???';
                        // todo;
                    })

                }
            },
            [LR_STATGE.talent.pageCode]: {
                page: talentPage,
				
                talentList: [],
                
                pressEnter: ()=>{
                    const talentList = this.#pages.talent.talentList;
                    
                },
                clear: ()=>{
                    this.#currentPage = 'talent';
                    
                    this.#totalMax = 20;
                },
            },
            [LR_STATGE.property.pageCode]: {
				"page":propertyPage
			},
            [LR_STATGE.trajectory.pageCode]: {
                page: trajectoryPage,
				
                
                clear: ()=>{
                    this.#currentPage = 'trajectory';
                    
                    this.#isEnd = false;
                },
                born: contents => {
                    
                }
            },
            [LR_STATGE.summary.pageCode]: {
                page: summaryPage,
				
                clear: ()=>{
                    this.#currentPage = 'summary';
                    
                    const lastExtendTalent = this.#life.getLastExtendTalent();
                    Array
                        .from(this.#talentSelected)
                        .sort((
                            {id:a, grade:ag},
                            {id:b, grade:bg},
                        )=>{
                            if(a == lastExtendTalent) return -1;
                            if(b == lastExtendTalent) return 1;
                            return bg - ag;
                        })
                        .forEach((talent, i)=>{
                            
                        });

                    const summaryData = this.#life.getSummary();
                    
                }
            },
        }

        
    }
	
    switch(page) {
		const p = this.#pages[page];
		if(this.#currentPageEntity){
			if(this.#currentPageEntity == p){
				// 当前页面
				return;
			}
			if(this.#currentPageEntity.preNextStage && this.#currentPageEntity.isStage() && p.isStage()){
				this.#currentPageEntity.preNextStage();
			}
		}
		
		let stage = p.page.stage;
		if(stage){
			this.#restartStage = stage;
		}
		if(this.#stageChangeFunc && stage){
			this.#stageChangeFunc(stage);
		}
        
        
        if(typeof p.page.mounted === 'function'){
            p.page.mounted()
        }
		this.#currentPageEntity = p;
    }

    hint(message, type='info') {
        if(this.#hintTimeout) {
            clearTimeout(this.#hintTimeout);
            this.#hintTimeout = null;
        }
		let typeTitleMap ={
			info:"信息",
			success:"恭喜"
		};
		let title = typeTitleMap[type] || "信息";
		
        uni.showModal({
			"title":title,
			"content":message,
			"showCancel":false
		});
    }

    setTheme(theme) {
        
    }
	
	auto(tick){
	    if(this.#autoTrajectory) {
	        clearInterval(this.#autoTrajectory);
	        this.#autoTrajectory = null;
	    } else {
	        if(this.#isEnd){
				return;
			}
	        this.#autoTrajectory = setInterval(()=>{
	            if(this.#isEnd) {
	                clearInterval(this.#autoTrajectory);
	                this.#autoTrajectory = null;
	            } else {
	                this.doTrajectoryNext();
	            }
	        }, tick);
	    }
	}
	
	reset(){
		// 重置选项
		this.#talentSelected = new Set();
		
		if(this.#selectTalentChangeFunc){
			this.#selectTalentChangeFunc(this.#talentSelected)
		}
		this.#randomTalentList = [];
		
		this.#isEnd = false;
		
		
	}
	restart(){
		this.reset();
		// 重新开始，进入选择天赋页面，首页点击开始
		this.switch(LR_STATGE.talent.pageCode);
	}
	
	nextStage(){
		let ns = stageHelper.nextStage(this.#restartStage);
		if(ns && ns.pageCode){
			this.switch(ns.pageCode);
		}
	}
	reload(){
		// 重新加载，返回初始状态
		this.switch(LR_STATGE.loading.pageCode);
		
		// dosomething!!
		
		this.switch(LR_STATGE.index.pageCode);
	}
    get times() {return this.#life?.times || 0;}
    set times(v) { if(this.#life) this.#life.times = v };
	
	get pages(){return this.#pages;}
	
	talentRandom(tnum){
		tnum = tnum || DEFAULT_TALENT_RANDOM_SIZE;
		this.#randomTalentList = this.#life.talentRandom(tnum);
		return this.#randomTalentList;
	}
	
	addListener(fname,func){
		if(fname =="stageChange"){
			this.#stageChangeFunc = func;
			return;
		}
		if(fname == "selectTalentChange"){
			this.#selectTalentChangeFunc = func;
			return;
		}
		if(fname == "lifePropertyChange"){
			this.#lifePropertyChangeFunc = func;
			return;
		}
		
		if(fname == "trajectory.lifePropertyChange"){
			this.#trajectoryFunc.lifePropertyChange = func;
			return;
		}
		
		if(fname == "trajectory.contentChange"){
			this.#trajectoryFunc.contentChange = func;
			return;
		}
		$$on(fname,func)
		return;
	}
	
	removeTalent(tid){
		
		let talent = {};
		for(let tt of this.#talentSelected ){
			if(tt.id == tid){
				talent = tt;
				break;
			}
		}
		
		this.#talentSelected.delete(talent);
		
		if(this.#selectTalentChangeFunc){
			this.#selectTalentChangeFunc(this.#talentSelected)
		}
		
		return this.getCurrentTalentTextInfo();
	}
	
	addTalent(tid){
		
		let ret ={
			"canNext":false,
			"nextText":"请选择" +this.#talentSelectMax +'个',
			"success":true,
			"errorMsg":""
		};
		if(this.#talentSelected.size==this.#talentSelectMax) {
		    ret.errorMsg = "只能选"+ this.#talentSelectMax +"个天赋"
			ret.success = false;
		    return ret;
		}
		let talent = this.#life.getTalentById(tid);
		const exclusive = this.#life.exclusive(
		    Array.from(this.#talentSelected).map(({id})=>id),
		    talent.id
		);
		if(exclusive != null) {
		    for(const { name, id } of this.#talentSelected) {
		        if(id == exclusive) {
					ret.errorMsg = `与已选择的天赋【${name}】冲突`
					ret.success = false;
					return ret;
		        }
		    }
			ret.errorMsg = `与其他天赋冲突`
			ret.success = false;
		    return ret;
		}
		
		this.#talentSelected.add(talent);
		if(this.#selectTalentChangeFunc){
			this.#selectTalentChangeFunc(this.#talentSelected)
		}
		return this.getCurrentTalentTextInfo();
	}
	
	getCurrentTalentTextInfo(){
		let ret ={
			"canNext":false,
			"nextText":"请选择" +this.#talentSelectMax +'个',
			"success":true,
			"errorMsg":""
		};
		if(this.#talentSelected.size== this.#talentSelectMax) {
			ret.canNext = true;
			ret.nextText = '开始新人生';
		}
		return ret;
	}
	propertyGroups(){
		return groups;
	}
	
	lifeStart(){
		return this.#pages[LR_STATGE["property"].pageCode].page.clickStart();
		
	}
	randomProperty(){
		this.#pages[LR_STATGE["property"].pageCode].page.random()
	}
	doTrajectoryNext(){
		if(this.#isEnd) return;
		const trajectory = this.#life.next();
		
		this.#trajectoryList.push(trajectory);
		this.doTrigger("trajectory.contentChange");
		this.doTrigger("trajectory.lifePropertyChange");
	}
	againGame(){
		this.times ++;
		this.reset();
		this.#life.talentExtend(this.#selectedExtendTalent);
		$$event("lifeGameAgain");
		this.switch(LR_STATGE.index.pageCode);
	}
	getLifeSummary(){
		return this.#life.getSummary();
	}
	getLastExtendTalent(){
		return this.#life.getLastExtendTalent();
	}
	getLifeSummaryJudge(){
		let bs = this.#life.getSummary();
		let ret={"summaryData":bs};
		ret.judgeShowResultList = [];
		const format = (discription, type)=>{
			const value = bs[type];
			const { judge, grade } = summary(type, value);
			return {
				"discription":discription,
				"type":type,
				"showCls":"grade"+grade,
				"value":value,
				"judge":judge
			};
		};
		
		ret.judgeShowResultList.push(format('颜值', 'CHR'));
		ret.judgeShowResultList.push(format('智力', 'INT'));
		ret.judgeShowResultList.push(format('体质', 'STR'));
		ret.judgeShowResultList.push(format('家境', 'MNY'));
		ret.judgeShowResultList.push(format('快乐', 'SPR'));
		ret.judgeShowResultList.push(format('享年', 'AGE'));
		ret.judgeShowResultList.push(format('总评', 'SUM'));
		return ret;
	}
	selectedExtendTalent(tid){
		this.#selectedExtendTalent = tid;
		$$event("selectedExtendTalentChange",{id:tid});
	}
	getCanExtendTalentList(){
		let setTalent = null;
		let ret = [];
		let stl = [];
		for(let tix of this.#talentSelected){
			if(tix.id == this.#selectedExtendTalent ){
				ret.push(tix);
			}else{
				stl.push(tix);
			}
		}
		ret = [...ret,...stl];
		this.selectedExtendTalent(ret[0].id);
		return ret;
	}
	getSpecialthanks(){
		return this.#specialthanks;
	}
	getTotal(){
		return this.#life.getTotal();
	}
	getAchievements(){
		return this.#life.getAchievements();
	}
}

export default App;
